/* 
Copyright (c) 2004,2005, 2006, 2007, 2008 University of Illinois 

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
AccessibilityExtension.ns(function() { with (AccessibilityExtension.LIB) {

	var AE = AccessibilityExtension.ns;  
	AE.dialogName = "accessext-form-focusinspector";	

	var bodynode
	var gColsForID;
	var gColsForWidth;
	var gCurrentNode;
	var statearray;
	var InitAccessibilityExtComplete = false;
	var _events=new Array("onblur","onclick","ondblclick","onfocus","onkeydown","onkeypress","onkeyup",
			"onmousedown","onmouseup","onmousemove","onmouseout","onmouseover","onresize","onload", "onchange");
	
	function attributesDisplayDetails() {}
	attributesDisplayDetails.prototype = {
		dataElementNames : ['order','name','value'],
		columnHeaders : ['column.header.order.label','column.header.attrname.label','column.header.value.label'],
		
		accessIssuesDataElementNames : [],
		accessIssuesMessages : [],
	}
	var attributesDisplayDetails = new attributesDisplayDetails();
	
	function attributesItem(order, name, value) {
		this.order = order;
		this.name = name;
		this.value= value;
	}
	attributesItem.prototype = {
		order : false,
		name : "",
		value : "",
		display: true,
		displayDetails: attributesDisplayDetails,
		getTreeItem : function(windoc) {
			return accesxt_generateTreeboxResults(windoc,this);
		}
	}
AccessibilityExtension.LIB.extend(AccessibilityExtension.LIB,
{
	InitAccessibilityExt: function() { 
		try {
			if (!InitAccessibilityExtComplete) {
				InitAccessibilityExtComplete = true;
				updatePointers(); 
		
				loadWairolesProperties();
		
				insertListeners();
				var grpelement = document.getElementById("widget-list-group");
				resetInspector(grpelement);
				addInspectorInstructions(grpelement);
				addInspectorResetButton(grpelement);
			}
		} catch (ex) {
			accessext_consoleDump('InitAccessibilityExt exception: ', ex);
		}
	},
	
	insertListeners: function() {
		try {
			bodynode[0].addEventListener("focus", getDetailsOfElementWithFocus, true);
			var iframes = bodynode[0].getElementsByTagName("iframe");
			for(var i=0; i<iframes.length; i++) {
				iframes[i].contentDocument.addEventListener("focus", getDetailsOfElementWithFocus, true);
			}
		
		} catch (ex) {
			accessext_consoleDump('insertListeners exception: ', ex);
		}
	},
	updatePointers: function() {
		try { // dialog way first
			AE.thewindow = window.opener.parent._content;
		} catch(e) {
			AE.thewindow = window.parent._content;
		}
		AE.mydoc = AE.thewindow.document;
		bodynode = AE.mydoc.getElementsByTagName("body");
		statearray = new Array();
	},
	
	displayEvents: function(obj, attachTo) {
		try {
			var nodeevents = null;
			var found = false;
			if(obj.node.getAttribute) {
				for (var j = 0; j < _events.length && !found; j++) {
					if (obj.node.hasAttribute(_events[j])) {
						found = true;
						// display the events
						nodeevents = newEventObject(0, obj.node);
						setMaxSeverityForArray(nodeevents.events);
			
						createTree(accessext_getBundleSingleString('inspector.events.hbox.label'), nodeevents.events,'',attachTo);
					}
				}
			}
		   	var AEinfo = createAccessibilityInformationBox(getNoteText(obj));
			attachTo.appendChild(AEinfo);
			if (nodeevents != null && (nodeevents.missingonfocus == true || nodeevents.missingonblur == true)) {
			 	var noteElement = document.getElementById("label-note-text");
				var currentContents = noteElement.getAttribute("value");
				if (null!= noteElement) {
			        noteElement.setAttribute("value",currentContents + getNoteText(nodeevents));
				}
				var row = document.getElementsByTagName('treerow');
				row[0].setAttribute('properties','failRow');
			}
	
		} catch (ex) {
			accessext_consoleDump('displayEvents exception: ', ex);
		}
	},
	
	resetInspector: function(attachTo) {
		while(attachTo.hasChildNodes()) {
			attachTo.removeChild(attachTo.firstChild);
		}
		var hbox = createXULElement("caption");
		hbox.setAttribute("label",accessext_getBundleSingleString('inspector.groupbox.label'));
		attachTo.appendChild(hbox);
	},
	
	addInspectorInstructions: function(attachTo) {
		var description = createXULElement("textbox");	
		description.setAttribute("readonly","true");	
		description.setAttribute("multiline","true");	
		description.setAttribute("value",accessext_getBundleSingleString('inspector.directions.line'));
		attachTo.appendChild(description);
	},
	
	addInspectorResetButton: function(attachTo) {
		createHboxButton(accessext_getBundleSingleString('button.refresh.label'), false, "AccessibilityExtension.LIB.InspectorRefresh();", accessext_getBundleSingleString('button.refresh.accesskey'), attachTo)
	},
	
	addColorContrast: function(node, attachTo) {
		try {
			var strTextColor;
			var cca_colorObj = contrastElement(2, node);
	
			if (cca_colorObj != null){
	            var clrObj = newColorObject(0, cca_colorObj);
	
				var asArray = new Array();
				asArray.push(clrObj);
				setMaxSeverityForArray(asArray);
				createTree(accessext_getBundleSingleString('contrast.label'), asArray,'', attachTo);
				
				var groupbox = createXULElement("groupbox");
				var hbox = createXULElement("hbox");
				hbox.setAttribute("flex","0");
				hbox.setAttribute("align","stretch");
				hbox.setAttribute("width","300");
				hbox.setAttribute("style",'color: ' + clrObj.color + '; background-color: ' + clrObj.bgcolor + ";");
				var label = createXULElement("label");
				var tmp = accessext_getBundleSingleString('example.text');
				tmp = tmp.replace('%1', clrObj.color);
				tmp = tmp.replace('%2', clrObj.bgcolor);
				label.setAttribute("value",tmp);
				hbox.appendChild(label);
				groupbox.appendChild(hbox);
				attachTo.appendChild(groupbox);
	
				return clrObj;
			}
		} catch (ex) {
			accessext_consoleDump('addColorContrast exception: ', ex);
		}
	},
	
	addStateManipElems: function(attachTo){
		var hboxCenter = createXULElement("hbox");
		var hboxL = createXULElement("hbox");
		var label = createXULElement("label");
		var textbox = createXULElement("textbox");
		var applyButton = createButton(accessext_getBundleSingleString('button.apply.label'), true, "setStateValue();", '');
		
		hboxL.setAttribute("align","left");
		hboxL.setAttribute("flex","1");
		label.setAttribute("id","state-value-label");
		label.setAttribute("value",accessext_getBundleSingleString('column.header.value.label'));
		label.setAttribute("disabled","true");
		textbox.setAttribute("id","state-value-textbox");	
		textbox.setAttribute("value","");	
		textbox.setAttribute("flex","1");
		textbox.setAttribute("maxwidth","50");	
		textbox.setAttribute("disabled","true");
					
		hboxL.appendChild(label);
		hboxL.appendChild(textbox);
		hboxL.appendChild(applyButton);
		
		var hboxR = createXULElement("hbox");
		hboxR.setAttribute("align","right");
		hboxR.setAttribute("flex","1");
		var toggleButton = createButton(accessext_getBundleSingleString('button.toggle.label'), true, "toggleState();", '');
		hboxR.appendChild(toggleButton);
		
		hboxCenter.appendChild(hboxL);
		hboxCenter.appendChild(hboxR);
		attachTo.appendChild(hboxCenter);
	},
	
	toggleState: function() {
		try {
			var stateTree = document.getElementById("treebox");
			var index = stateTree.currentIndex;
			var currVal = statearray[index].value.toLowerCase();
			var newVal = -1;
			var values;
			//HARD CODED VALUES !!! 
			switch (statearray[index].state.toLowerCase()) {
				case 'checked':	values = new Array('true','false','mixed'); break;
				case 'expanded': values = new Array('true','false','undefined'); break;
				case 'grab': values = new Array('true','supported','false'); break;
				case 'pressed': values = new Array('true','false','mixed','undefined'); break;
				case 'selected': values = new Array('true','false','undefined'); break;
			}
			for (var i = 0; i < values.length; i++) {
				if (values[i] == currVal) { (i+1 == values.length) ? newval =0 : newVal = i + 1;}
			}
		   if (newVal == -1) newVal = 0;
			gCurrentEvent.target.setAttribute('aria-' + statearray[index].state, values[newVal]);	
			getDetailsOfElementWithFocus(gCurrentEvent); // refresh side bar
		} catch (ex) {
			accessext_consoleDump('toggleState exception: ', ex);
		}
	},
	
	setStateValue: function() {
		try {
			function isInteger(sText)	{
				var ValidChars = "0123456789";
				if (sText.length == 0) return false;
				for (i = 0; i < sText.length; i++) { 
					if (ValidChars.indexOf(sText.charAt(i)) == -1) return false;
				}
				return true;
			}		
			var stateTree = document.getElementById("treebox");
			var index = stateTree.currentIndex;
			var stateValueEle = document.getElementById("state-value-textbox");
			if (stateValueEle.hasAttribute("value")) {
				var value = stateValueEle.value;
				var min = 0;
				var max = 0;
				var indexValueNow = 0;
				if (isInteger(value)) {
					for (var i = 0; i < statearray.length; i++) {
						if (statearray[i].state.toLowerCase() == 'valuemin') min = statearray[i].value;
						if (statearray[i].state.toLowerCase() == 'valuemax') max = statearray[i].value;
					}
					if (parseInt(value) < parseInt(min)) {alert(accessext_getBundleSingleString('valuenow.toosmall').replace('%1', min)); return;}
					if (parseInt(value) > parseInt(max)) {alert(accessext_getBundleSingleString('valuenow.toolarge').replace('%1', max)); return;}
					gCurrentEvent.target.setAttribute('aria-' + statearray[index].state,value);	
					statearray[index].value = value;
					getDetailsOfElementWithFocus(gCurrentEvent);	
				} else {				
					alert(accessext_getBundleSingleString('valuenow.invalid'))
				}
			}
		} catch (ex) {
			accessext_consoleDump('setStateValue exception: ', ex);
		}	
	},
	
	accessext_state_select: function() {
		try {
			var stateTree = document.getElementById("treebox");
			var index = stateTree.currentIndex;
			if (index < 0 || index > statearray.length) {
				return false;
			}
			
			var togglebutton = document.getElementById(accessext_getBundleSingleString('button.toggle.label'));
			if (null != togglebutton) {
				if (statearray[index]) {
					var toggable = ['checked','expanded', 'grab','pressed','selected','sort'];
					togglebutton.disabled = (toggable.indexOf(statearray[index].state.toLowerCase()) == -1);
				}
			}
			var valuelabel = document.getElementById("state-value-label");
			var applybutton = document.getElementById(accessext_getBundleSingleString('button.apply.label')); 
			var valueTextbox = document.getElementById("state-value-textbox");
			if (null != applybutton && null != valueTextbox) {
				if (statearray[index] && statearray[index].state.toLowerCase() == 'valuenow') {
					valuelabel.disabled = applybutton.disabled = valueTextbox.disabled = false; 
				}
				else {
					valuelabel.disabled = applybutton.disabled = valueTextbox.disabled = true;
				}
			}
	
			return true;
		} catch (ex) {
			accessext_consoleDump('accessext_state_select exception: ', ex);
		}
	},
	
	accessext_tree_autoselect_state: function() {
		try {
			var stateTree = document.getElementById("treebox");
			if (statearray.length > 0 && stateTree.currentIndex < 0) {
				stateTree.currentIndex=0;
				stateTree.view.selection.select(0);
			}
		} catch (ex) {
			accessext_consoleDump('accessext_tree_autoselect_state exception: ', ex);
		}
	},
	
	getDetailsOfElementWithFocus: function(event) {
		try {
			var found = false;
			var nodeName = event.target.nodeName.toLowerCase();
			var grpelement = document.getElementById("widget-list-group");
			gCurrentEvent = event;
			resetInspector(grpelement);
			
			var role = readRole(event.target);
			
			if (nodeName == "a" ) {
				var linkObj = newLinkObject(0, event.target);
				var asArray = new Array();
				asArray.push(linkObj);
				setMaxSeverityForArray(asArray);
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.nodetype.hbox.label'), nodeName, 'false', grpelement);					
				createTree(accessext_getBundleSingleString('inspector.link.hbox.label'), asArray, '',grpelement);
				found = linkObj;
			}else if (nodeName == "area" ) {
				var imageMapObj = newImageMapItem(event.target, 0);
				var asArray = new Array();
				asArray.push(imageMapObj);
				setMaxSeverityForArray(asArray);
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.nodetype.hbox.label'), nodeName, 'false', grpelement);					
				createTree(accessext_getBundleSingleString('inspector.maplink.hbox.label'), asArray, '',grpelement);
				found = imageMapObj;
			}else if (nodeName == "object" || nodeName == "applet" || nodeName == "embed" ) {
				var htmlObj = newhtmlObject(event.target, 0);
				setMaxSeverityForArray(htmlObj.attributes);
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.nodetype.hbox.label'), nodeName, 'false', grpelement);					
				createTextboxWithLabel(accessext_getBundleSingleString('column.header.text.label'), htmlObj.objectTitle, 'false', grpelement);					
				createTree(accessext_getBundleSingleString('inspector.objectlink.hbox.label'), htmlObj.attributes, '',grpelement);
				createTextboxWithLabel(accessext_getBundleSingleString('label.textcontent'), htmlObj.displayText, 'true', grpelement);					
				found = htmlObj;
			}else if (role != null ) {
				var widgetObj = newWidgetObject(0, event.target);
				setMaxSeverityForArray(widgetObj.states);
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.nodetype.hbox.label'), nodeName, 'false', grpelement);					
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.role.hbox.label', 'false'),widgetObj.role, 'false', grpelement);					
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.accessiblename.hbox.label'), widgetObj.getStateValueInPage('labelledby'), 'true', grpelement);					
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.description.hbox.label'), widgetObj.getStateValueInPage('describedby'), 'true', grpelement);	
				if (widgetObj.states.length > 0)	{
					var stGroupBox = createTree(accessext_getBundleSingleString('inspector.states.hbox.label'), widgetObj.states, "AccessibilityExtension.LIB.accessext_state_select();",grpelement);
					addStateManipElems(stGroupBox);
					statearray = widgetObj.states;
					accessext_tree_autoselect_state();
				}			
				found = widgetObj;
			}else if (event.target.type != null){ //form element
				var formElementObj = newFormElementObject(event.target, 'NA');
				hbox = createTextboxWithLabel(accessext_getBundleSingleString('inspector.nodetype.hbox.label'), nodeName, 'false', grpelement);					
				var asArray = new Array();
				asArray.push(formElementObj);
				setMaxSeverityForArray(asArray);
				createTree(accessext_getBundleSingleString('inspector.formelement.hbox.label'), asArray, '',grpelement);
				found = formElementObj;
			}
			clrObj = addColorContrast(event.target, grpelement);
			if (event.target.attributes.length > 0) {
				var attrArray = new Array();
				for(var i=0; i< event.target.attributes.length; i++ ) {
					if (event.target.attributes[i].name.toLowerCase().indexOf('aria-') == -1 ) {
						attrArray[attrArray.length]= new attributesItem(i+1,event.target.attributes[i].name,event.target.attributes[i].value);
					}
				}
				createTree(accessext_getBundleSingleString('inspector.attributes.hbox.label'), attrArray, '',grpelement);
			}
	
	
			if (found != false){
				displayEvents(found, grpelement);
		   		accessext_scrollAndHighlightNode(event.target); //  in the page we are testing
		   		
				if (clrObj != null) {
					var noteElement = document.getElementById("label-note-text");
					var currentContents = noteElement.getAttribute("value");
					if (null!= noteElement) {
				        noteElement.setAttribute("value", currentContents + getNoteText(clrObj));	
					}
				}
	
			} else{
				createTextboxWithLabel(accessext_getBundleSingleString('inspector.nodetype.hbox.label'), nodeName, 'false', grpelement);					
		   		if (event.target.nodeName != '#document') {
					accessext_scrollAndHighlightNode(event.target); // in the page we are testing
				}
			}
			Inspector_loadDialogPrefs(); //rest all of the colums widths
			
			addInspectorResetButton(grpelement);
	//			createHboxButton("View Summary", false, "accessExtSummaryAsBrowserPage();", accessext_getBundleSingleString('button.refresh.accesskey'), attachTo); used to test a new function
		} catch (ex) {
			accessext_consoleDump('getDetailsOfElementWithFocus exception: ', ex);
		}
	},
	
	InspectorRefresh: function() {
		try {
			bodynode[0].removeEventListener("focus", getDetailsOfElementWithFocus, false);
	
			updatePointers();
			insertListeners();
			var grpelement = document.getElementById("widget-list-group");
			resetInspector(grpelement);
			addInspectorInstructions(grpelement);
			addInspectorResetButton(grpelement);
		} catch (ex) {
			accessext_consoleDump('InspectorRefresh exception: ', ex);
		}
	},
	
	Inspector_loadDialogPrefs: function() {
		try {
			gColsForID = '';
			gColsForWidth = '';
			var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("");
	
			var dialogID = this.name; //duplicates when in sidebar
			if (dialogID == 'sidebar') {dialogID = sidebarNameToTitle();}
			var prefStr = dialogID + '.dialogWidth';
			if (pref.prefHasUserValue(prefStr)) {
				var value = pref.getCharPref(prefStr);
				if (value != '') { accessext_setWidth("vb", value); }
			}
			prefStr = dialogID + '.dialogHeight';
			if (pref.prefHasUserValue(prefStr)) {
				var value = pref.getCharPref(prefStr);
				if (value != '') { accessext_setHeight("vb",value); }
			}
			var valueForID = '';
			prefStr = dialogID + '.showColumns';
			if (pref.prefHasUserValue(prefStr)) {
				valueForID = pref.getCharPref(prefStr);
			}
			if (valueForID == '') {
				valueForID = 'Link-list-header-text,Link-list-header-link,Colour-Contrast-list-header-nodeName,Colour-Contrast-list-header-type,Colour-Contrast-list-header-contrastRatio,';
				valueForID += 'Events-list-header-event,Map-link-list-header-linkText,Map-link-list-header-linkHREF,Map-link-list-header-redundantText,';
				valueForID += 'Object-Link-list-header-name,Object-Link-list-header-value,';
				valueForID += 'Form-Element-list-header-label,Form-Element-list-header-type,Form-Element-list-header-text,';
			}
	
			var valueForWidth = '';
			prefStr = dialogID + '.ColumnWidths';
			if (pref.prefHasUserValue(prefStr)) {
				valueForWidth = pref.getCharPref(prefStr);
			}	
			if (valueForID != '') { 
				var colsForID = valueForID.split(',');
				var colsForWidth = valueForWidth.split(',');
				gColsForID = colsForID;
				gColsForWidth = colsForWidth;
				for (var i = 0; i < colsForID.length; i++) {
					accessext_setVisibleColumn(colsForID[i]);
					if (colsForWidth[i] != '') { accessext_setWidth(colsForID[i], colsForWidth[i]); }
				}			
			}
			return true;
		} catch (ex) {
			accessext_consoleDump('Inspector_loadDialogPrefs exception: ', ex);
		}
	},
	
	removeColHeader: function(headerPrefix) {
		for (var i = 0; i < gColsForID.length; i ++) {
			var loc = gColsForID[i].indexOf(headerPrefix);
			if (loc > -1) {
				gColsForID.splice(i,1);
				gColsForWidth.splice(i,1);
			} 
		}	
		return;
	},
	
	Inspector_saveDialogPrefs: function() {
		try {
			var prefNameVal = "";
			var prefWidthVal = "";
			var prevHeaderPrefix = "";
			
			var cols = document.getElementsByTagName("*");
	//		var cols = document.getElementsByTagName("treecol"); //only works in FF2
			for (var i = 0; i < cols.length; i ++) {
				if (cols[i].id) {
					var loc = cols[i].id.indexOf('list-header-');
					if (loc > -1 && cols[i] && !cols[i].hidden) {
						prefNameVal = prefNameVal + cols[i].getAttribute("id") + ",";
						prefWidthVal = prefWidthVal + cols[i].getAttribute("width") + ",";
						
						//remove the Names & Widths of the strings of the list(s) we are currently displaying from gColsForID & gColsForWidth
						//search for anything starting with a similar header	
						var headerPrefix = cols[i].getAttribute("id").substring(0,loc + 12);
						if (headerPrefix != prevHeaderPrefix) {
							removeColHeader(headerPrefix);
							prevHeaderPrefix = headerPrefix
						}				
					}
				}
			}
			
			if (prefNameVal.length > 0) { prefNameVal = prefNameVal.substring(0,prefNameVal.length-1); }
			if (prefWidthVal.length > 0) { prefWidthVal = prefWidthVal.substring(0,prefWidthVal.length-1); }
			
			//now append this lists columns back to the list 
			prefNameVal += ',' + gColsForID.toString();
			prefWidthVal += ',' + gColsForWidth.toString();
			
			var dialogID = this.name; //duplicates when in sidebar
			if (dialogID == 'sidebar') {dialogID = sidebarNameToTitle();}
			var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("");
			var element = document.getElementById("vb");
			pref.setCharPref(dialogID + '.dialogWidth',element.width);
			pref.setCharPref(dialogID + '.dialogHeight',element.height);
			pref.setCharPref(dialogID + '.showColumns',prefNameVal);
			pref.setCharPref(dialogID + '.ColumnWidths',prefWidthVal);
			return true;
		} catch (ex) {
			accessext_consoleDump('Inspector_saveDialogPrefs exception: ', ex);
		}
	},
	CleanUp: function() {
		return accessext_GlobalCleanup();
	}
});
	if (AccessibilityExtension.LIB.InitAccessibilityExt) AccessibilityExtension.LIB.InitAccessibilityExt();	
}});